package item53;

import java.util.Arrays;
import java.util.Set;

/**
 * 第53条：接口优先于反射机制
 */
public class Main01 {

    // Reflective instantiation with interface access
    // 具有接口访问的反射实例化
    public static void main(String[] args) {

        // 使用反射付出的代价
        // 1.丧失了编译时类型检查的好处。包括异常检查。
        // 反射方式调用不存在的或者不可访问的方法，运行时将失败，还要采取特别的预防措施。
        // 2.执行反射访问所需要的代码非常笨拙和冗长。
        // 3.性能损失。

        // 通常，普通应用程序在运行时不应该以反射方式访问对象。

        // 如果只是以非常有限的形式使用反射机制，虽然也要付出少许代价，但是可以获得许多好处。

        // 编译时无法获取的类，编译时存在适当的接口或者超类，如果是这种情况，就可以反射方式创建实例，
        // 然后通过它们的接口或者超类，以正常的方式访问这些实例。

        // Translate the class name into a class object
        // 将类名转换为类对象
        Class<?> c1 = null;
        try {
            c1 = Class.forName("java.util.HashSet");
        } catch (ClassNotFoundException e) {
            System.err.println("Class not found.");
            System.exit(1);
        }

        // Instantiate the class
        Set<String> s = null;
        try {
            s = (Set<String>)c1.newInstance();
        } catch (InstantiationException e) {
            System.err.println("Class not accessible.");
            System.exit(1);
        } catch (IllegalAccessException e) {
            System.err.println("Class not instantiable.");
            System.exit(1);
        }

        // exercise the set
        String[] a = {"1","2","3"};
        s.addAll(Arrays.asList(a).subList(1,a.length));
        System.out.println(s);

    }

}
